Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/LizandroCanul/back_sdo/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The API uses NestJS’s built-in HTTP exceptions to provide standardized error responses. All exceptions follow a consistent JSON structure for easy client-side handling.

Standard Error Response Format

All HTTP exceptions return this structure:
{
  "statusCode": 400,
  "message": "Error description or array of messages",
  "error": "Error Type Name"
}

Common HTTP Exceptions

BadRequestException (400)

Used for validation errors and invalid input.
import { BadRequestException } from '@nestjs/common';

if (!user) {
  throw new BadRequestException('El correo electrónico ya está registrado.');
}

if (favorite) {
  throw new BadRequestException('Esta obra ya está en tus favoritas');
}
Common Use Cases:
  • Duplicate entries
  • Invalid data format
  • Business rule violations
  • Already existing resources
Location Examples:
  • /home/daytona/workspace/source/src/users/users.service.ts:161
  • /home/daytona/workspace/source/src/users/users.service.ts:105

UnauthorizedException (401)

Used when authentication fails or credentials are invalid.
import { UnauthorizedException } from '@nestjs/common';

@Post('login')
async login(@Body() body) {
  const user = await this.authService.validateUser(body.email, body.password);
  
  if (!user) {
    throw new UnauthorizedException('Credenciales inválidas');
  }

  return this.authService.login(user);
}
Common Use Cases:
  • Invalid login credentials
  • Missing JWT token
  • Expired token
  • Invalid token signature
Location: /home/daytona/workspace/source/src/auth/auth.controller.ts:14

ForbiddenException (403)

Used when a user is authenticated but lacks permission to access a resource.
import { ForbiddenException } from '@nestjs/common';

@Get(':id')
findOne(
  @Param('id') id: string,
  @GetUser() user: any
) {
  // User is logged in but trying to access another user's profile
  if (user.roles !== 'admin' && user.userId !== id) {
    throw new ForbiddenException('No tienes permiso para ver este perfil.');
  }
  return this.usersService.findOne(id);
}
Common Use Cases:
  • Accessing another user’s data
  • Non-admin trying admin operations
  • Modifying resources without ownership
  • Role-based access denial
Location Examples:
  • /home/daytona/workspace/source/src/users/users.controller.ts:52
  • /home/daytona/workspace/source/src/users/users.controller.ts:66
  • /home/daytona/workspace/source/src/users/users.controller.ts:89

NotFoundException (404)

Used when a requested resource doesn’t exist.
import { NotFoundException } from '@nestjs/common';

async findOne(id: string) {
  const user = await this.userRepository.findOneBy({ id });
  
  if (!user) {
    throw new NotFoundException('Usuario no encontrado');
  }
  
  return user;
}
Common Use Cases:
  • Entity not found by ID
  • Resource deleted or never existed
  • Invalid foreign key references
Location Examples:
  • /home/daytona/workspace/source/src/users/users.service.ts:49
  • /home/daytona/workspace/source/src/obras/obras.service.ts:115
  • /home/daytona/workspace/source/src/dependencias/dependencias.service.ts:34

ConflictException (409)

Used when a request conflicts with the current state.
import { ConflictException } from '@nestjs/common';

async create(dto: CreateObraDto) {
  try {
    return await this.obraRepository.save(dto);
  } catch (error) {
    if (error.code === '23505') { // Postgres unique violation
      throw new ConflictException('La clave única ya existe');
    }
    throw error;
  }
}
Common Use Cases:
  • Unique constraint violations
  • State conflicts (e.g., deleting an active record)
  • Race conditions
Location: /home/daytona/workspace/source/src/obras/obras.service.ts:1

Real-World Error Examples

Authentication Flow

1

User submits login

POST /auth/login with email and password
2

Validation check

If credentials are invalid → UnauthorizedException
{
  "statusCode": 401,
  "message": "Credenciales inválidas",
  "error": "Unauthorized"
}
3

Success response

If valid → return JWT token

Authorization Flow

1

User makes authenticated request

GET /users/{someOtherId} with valid JWT
2

Permission check

If not admin AND not own profile → ForbiddenException
{
  "statusCode": 403,
  "message": "No tienes permiso para ver este perfil.",
  "error": "Forbidden"
}
3

Success response

If authorized → return user data

Resource Operations

// GET /obras/999
const obra = await this.obraRepository.findOneBy({ id: 999 });

if (!obra) {
  throw new NotFoundException('Obra 999 no encontrada.');
}
// Response: 404 Not Found

Permission Error Patterns

User Resource Protection

@Get(':id')
findOne(@Param('id') id: string, @GetUser() user: any) {
  if (user.roles !== 'admin' && user.userId !== id) {
    throw new ForbiddenException('No tienes permiso para ver este perfil.');
  }
  return this.usersService.findOne(id);
}
Locations:
  • /home/daytona/workspace/source/src/users/users.controller.ts:45-54
  • /home/daytona/workspace/source/src/users/users.controller.ts:58-68
  • /home/daytona/workspace/source/src/users/users.controller.ts:81-91

Validation Errors

Validation errors are automatically handled by the ValidationPipe and return 400 Bad Request:
export class CreateUserDto {
  @IsEmail()
  email: string;

  @MinLength(6)
  password: string;
}
Validation errors are configured in main.ts:8-14 with the global ValidationPipe.

Error Handling Best Practices

Be Specific

Use descriptive error messages that help users understand what went wrong.
throw new NotFoundException(`Obra ${id} no encontrada.`);

Choose Correct Status

  • 400: Bad input
  • 401: Not authenticated
  • 403: Not authorized
  • 404: Not found
  • 409: Conflict

Avoid Exposing Internals

Don’t leak database errors or stack traces to clients in production.
catch (error) {
  throw new BadRequestException('No se pudo crear el registro');
}

Consistent Messages

Keep error messages in the same language throughout the API (Spanish in this project).

Quick Reference

401 Unauthorized: User is not logged in or token is invalid.
throw new UnauthorizedException('Credenciales inválidas');
403 Forbidden: User is logged in but doesn’t have permission.
throw new ForbiddenException('No tienes permiso para esta acción.');
400 Bad Request: General validation errors or bad input.
throw new BadRequestException('Email ya registrado');
409 Conflict: Specific state conflicts (usually from database constraints).
throw new ConflictException('Clave única duplicada');
Catch database errors and convert to appropriate HTTP exceptions:
try {
  await this.repository.save(entity);
} catch (error) {
  if (error.code === '23505') { // Unique violation
    throw new ConflictException('Registro duplicado');
  }
  if (error.code === '23503') { // Foreign key violation
    throw new BadRequestException('Referencia inválida');
  }
  throw new InternalServerErrorException('Error del servidor');
}

HTTP Status Code Summary

Status CodeExceptionUse CaseExample
400BadRequestExceptionInvalid input, validation errors”Email ya registrado”
401UnauthorizedExceptionAuthentication failure”Credenciales inválidas”
403ForbiddenExceptionPermission denied”No tienes permiso”
404NotFoundExceptionResource not found”Obra 123 no encontrada”
409ConflictExceptionState conflict”Clave única duplicada”
500InternalServerErrorExceptionServer error”Error del servidor”

Next Steps

Database Schema

Learn about entity relationships

Validation

Understand request validation